﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Infinite.Systems.Util.Library.Base;
using System.DirectoryServices;
using System.DirectoryServices.AccountManagement;
using Infinite.Systems.Util.Library.Messaging;
using System.Configuration;

namespace Infinite.Systems.Util.Library
{
    /// <summary>
    /// Represents a type of ActiveDirectoryReminder , holds method for sending notification to user through email
    /// </summary>
    public class ActiveDirectoryEmailReminder : IActiveDirectoryReminder
    {
        #region "Public Methods"
        /// <summary>
        /// Initializes the default properties of the class
        /// </summary>
        /// <param name="ldapPath">Path of the Active Directory</param>
        /// <param name="filterQuery">Filter Query for AD</param>
        /// <param name="policyDays">Policy Days Configured in AD</param>
        /// <param name="reminderDayList">Reminder List. If program is used as a schedule service then this list will provide program the day numbers on which reminder is to be sent before expiration </param>
        public ActiveDirectoryEmailReminder(string ldapPath, string filterQuery, int policyDays, string reminderDayList)
        {
            this.LDAPPath = ldapPath;
            this.PasswordPolicyDay = policyDays;
            this.ADFilterQuery = filterQuery;
            this.ReminderDayList = reminderDayList;

        }


        /// <summary>
        /// Find All AD Users whose password will expire in 
        /// </summary>
        /// <returns>List of IADUser</returns>
        public List<IADUser> FindAllForExpirationReminder()
        {

            SearchResultCollection lstResult = null;
            PrincipalContext ctx = new PrincipalContext(ContextType.Domain);
            DirectoryEntry entry = null;
            UserPrincipal user;
            List<IADUser> lstAduser = new List<IADUser>();
            lstResult = this.GetADFilterResult();

            try
            {
                foreach (SearchResult result in lstResult)
                {
                    entry = result.GetDirectoryEntry();
                    user = UserPrincipal.FindByIdentity(ctx, entry.Properties["Name"].Value.ToString());

                    if (user != null && !user.PasswordNeverExpires && user.LastPasswordSet.HasValue)
                    {
                        DateTime passwordExpirationDate = user.LastPasswordSet.Value.AddDays(this.PasswordPolicyDay);
                        string[] dayArray = this.ReminderDayList.Split(',');
                        //Console.WriteLine("Password Expiry in " + adUser.PasswordExpirationDate.Subtract(DateTime.Now).Days.ToString());
                        if (dayArray.Contains(passwordExpirationDate.Subtract(DateTime.Now).Days.ToString()))
                        {
                            ADUser adUser = new ADUser();
                            adUser.DisplayName = user.DisplayName;
                            adUser.GivenName = user.GivenName;
                            adUser.UserName = user.Name;
                            adUser.Email = user.EmailAddress;
                            adUser.DayRemaining = passwordExpirationDate.Subtract(DateTime.Now).Days;
                            adUser.PasswordExpirationDate = passwordExpirationDate;
                            adUser.Email = user.EmailAddress;
                            lstAduser.Add(adUser);
                        }
                    }
                }

                return lstAduser;
            }
            catch (Exception ex) { throw; }

        }
       

        /// <summary>
        /// Send Alert to Users
        /// </summary>
        public void SendAlert(List<IADUser> lstadUsers)
        {

            string filePath = ConfigurationManager.AppSettings["EmailTemplateFilePath"].ToString();
            string subject = ConfigurationManager.AppSettings["EmailSubject"].ToString();
            string emailFrom = ConfigurationManager.AppSettings["EmailFrom"].ToString(); 
            EmailPacket emailPacket = null;
            string defaultBodyContent = string.Empty;
            try
            {
                if (lstadUsers.Count > 0)
                {
                    emailPacket = new EmailPacket(filePath, subject, emailFrom);
                    defaultBodyContent = emailPacket.BodyContent;
                    
                    foreach (IADUser user in lstadUsers)
                    {
                        
                        emailPacket.EmailRecipient =  user.Email;//user.Email; //todo: remove the test email after testing
                        emailPacket.BodyContent = emailPacket.BodyContent.Replace("$User", user.GivenName);
                        emailPacket.BodyContent = emailPacket.BodyContent.Replace("$Day_Count", Convert.ToString(user.DayRemaining));
                        emailPacket.BodyContent = emailPacket.BodyContent.Replace("$Date", user.PasswordExpirationDate.ToShortDateString());
                        Mail.SendEmail(emailPacket);
                        emailPacket.BodyContent = defaultBodyContent; //reset the body content to its original state

                    }

                }
            }

            catch (ConfigurationErrorsException ex) { throw; }

            catch (Exception ex)
            {
                throw;
            }


        }
        #endregion

        #region "PrivateMethods
        /// <summary>
        /// Gets AD Filter Result Collection
        /// </summary>
        /// <returns>SearchResultCollection</returns>
        private SearchResultCollection GetADFilterResult()
        {
            DirectorySearcher search = null;
            SearchResultCollection lstResult = null;

            using (DirectoryEntry de = new DirectoryEntry(this.LDAPPath))
            {

                //Add Users Whose Accounts are set to expired.
                search = new DirectorySearcher(de, this.ADFilterQuery);
                lstResult = search.FindAll();
            }

            return lstResult;

        }
        #endregion

        #region "Public Properties"
        /// <summary>
        /// Path of the LDAP
        /// </summary>
        public string LDAPPath { get; set; }
        /// <summary>
        /// Reminder Day List. This List is to be configured in the app.config file
        /// </summary>
        public string ReminderDayList { get; set; }

        /// <summary>
        /// Active Directory Filter
        /// </summary>
        public string ADFilterQuery { get; set; }
        /// <summary>
        /// Gets or Sets number of day after which the window's domain password expire
        /// </summary>
        public int PasswordPolicyDay { get; set; }
        #endregion
    }
}
